#include <linux/init.h>
#include <linux/tty.h>
#include <linux/device.h>
#include <linux/export.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/export.h>
#include <linux/mm_types.h>
#include <linux/mm.h>
#include <linux/slab.h>

#define   MM_SIZE   1024 * 4
#define   MIN(x,y)  (x < y ? x : y)

static int major;
static char *buf = "hello spin_lock";
struct class * hello_class;
int lock_flag = 0;
spinlock_t lock;

static int hello_open (struct inode *node, struct file *filp)
{
	printk("hello_open, lock_flag = %d\n",lock_flag);
	
	spin_lock(&lock);
	if(lock_flag){
		spin_unlock(&lock);
		printk("\n driver on using !!!\n");
		return -EBUSY;
	}
	lock_flag++;
	spin_unlock(&lock);
	printk("\ndriver open success !!!\n");
	return 0;
}

static ssize_t hello_read (struct file *filp, char  *buff, size_t size, loff_t *offset)
{
	int err;
	err = copy_to_user(buff, buf, MIN(MM_SIZE, size));
	printk("hello_read\n");
	return MIN(MM_SIZE, size);
}

static ssize_t hello_write (struct file *filp, const char  *buf, size_t size, loff_t *offset)
{
	printk("hello_write\n");
	return size;
}

static int hello_release (struct inode *node, struct file *filp)
{
	spin_lock(&lock);
	if(lock_flag){
		lock_flag--;
	}
	spin_unlock(&lock);
	printk("hello_release\n");
	return 0;
}


/*定义 file_operations 结构体*/
static const struct file_operations hello_drv = {
    .owner 		= THIS_MODULE,
	.read		= hello_read,
	.write		= hello_write,
	.open		= hello_open,
	.release    = hello_release,
};


/*入口函数*/
static int hello_init(void)
{
	//设备号，注册设备
	major = register_chrdev(0,"hello_drv",&hello_drv);

	hello_class = class_create(THIS_MODULE, "hello_class");

	device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello");

	//初始化自旋锁
	spin_lock_init(&lock);
	
	return 0;
}

/*退出函数*/
static void hello_exit(void)
{
	device_destroy(hello_class, MKDEV(major, 0));
	class_destroy(hello_class);
	unregister_chrdev(major,"hello_drv");
}	

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
